package com.czm.art_light.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.czm.art_light.annotation.CacheWithLock;
import com.czm.art_light.constant.CommonConsts;
import com.czm.art_light.constant.RedisConstant;
import com.czm.art_light.context.UserActionHandlerChainContext;
import com.czm.art_light.entity.*;
import com.czm.art_light.manager.mq.producer.AmqpMsgProducer;
import com.czm.art_light.mapper.*;
import com.czm.art_light.param.request.ArtWorkReqDto;
import com.czm.art_light.param.request.PageReqDto;
import com.czm.art_light.param.request.UserActionReqDto;
import com.czm.art_light.param.response.*;
import com.czm.art_light.service.ArtStatisticsService;
import com.czm.art_light.service.ArtUserActionsService;
import com.czm.art_light.service.ArtWorkService;
import com.czm.art_light.util.UserHolderUtility;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;


/**
 * 作品信息 服务类
 */
@Service
public class ArtWorkServiceImpl implements ArtWorkService {
    @Autowired
    private ArtWorkMapper artWorkMapper;

    @Autowired
    private ArtArtistMapper artArtistMapper;

    @Autowired
    private ArtTopicMapper artTopicMapper;

    @Autowired
    private ArtCategoryMapper artCategoryMapper;

    @Autowired
    private ArtMovementMapper artMovementMapper;

    @Autowired
    private ArtUserLikesMapper artUserLikesMapper;

    @Autowired
    private ArtUserActionsService artUserActionsService;

    @Autowired
    private ArtUserActionsMapper artUserActionsMapper;

    @Autowired
    private ArtStatisticsService artStatisticsService;

    @Autowired
    private ArtStatisticsMapper artStatisticsMapper;

    @Autowired
    private AmqpMsgProducer amqpMsgProducer;

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private UserActionHandlerChainContext userActionHandlerChainContext;


    /**
     * 根据作品id查找对应的作品信息
     */
    @Transactional
    @Override
    public ArtWorkInfoRespDto getById(Integer id) {
        // 判断布隆过滤器中是否存在数据
        RBloomFilter<Integer> rBloomFilter = redissonClient.getBloomFilter(RedisConstant.ART_WORK_BLOOM_FILTER_KEY);
        //不存在直接返回null
        if (!rBloomFilter.contains(id)) {
            return null;
        }

        ArtWork artWork = artWorkMapper.getById(id);
        if (artWork == null) {
            return null;
        } else {
            //获取当前线程的用户id
            Integer userId = UserHolderUtility.getUserId();
/*            // 1.将用户点击该艺术画作品的行为记录到数据库中
            artUserActionsService.recordUserActions(ArtUserActions.builder()
                    //用户id
                    .userId(userId)
                    //作品id
                    .workId(artWork.getId())
                    //操作类型：点击
                    .actionType(CommonConsts.ActionType.VIEW.getValue())
                    //操作时间(当前时间)
                    .actionTime(LocalDateTime.now())
                    .build());*/
            // 2.该作品的点击量加+1
//            artStatisticsService.incrementClickCount(artWork.getId());

            //采用责任链嵌套策略设计模式，根据不同行为灵活执行相应业务逻辑。
            userActionHandlerChainContext.execute(new UserActionReqDto(userId, CommonConsts.ActionType.VIEW, artWork.getId()));


            // 3. 从数据库中查找用户是否喜欢该艺术作品
            //默认用户不喜欢，如果数据库中有数据，则根据数据库的数据
            boolean isLiked = false;
            ArtUserLikes artUserLikes = artUserLikesMapper.getByUserIdAndWorkId(userId, artWork.getId());
            if (artUserLikes != null && artUserLikes.getIsLiked() != null) {
                isLiked = artUserLikes.getIsLiked();
            }

            // 4. 从缓存中查找该艺术作品的其余信息
            // 通过代理对象调用（需开启exposeProxy）
            ArtWorkService proxy = (ArtWorkService) AopContext.currentProxy();
            ArtWorkInfoRespDto artWorkInfoRespDto = proxy.artworkInfoCache(artWork);
            artWorkInfoRespDto.setIsLiked(isLiked);

            return artWorkInfoRespDto;

            //作品所属的话题基本信息（可能属于多个话题）
            /*Integer topicId = artWork.getTopicId();
            ArtTopic artTopic = artTopicMapper.getById(topicId);
            List<ArtTopicBasicInfoRespDto> artTopicBasicInfoRespDtoList = new ArrayList<>();
            artTopicBasicInfoRespDtoList.add(ArtTopicBasicInfoRespDto.builder()
                    //话题id
                    .id(artTopic.getId())
                    //话题名称
                    .topicName(artTopic.getTopicName())
                    .build());

            //作品所属的流派基本信息（可能属于多个流派）
            Integer movementId = artWork.getMovementId();
            ArtMovement artMovement = artMovementMapper.getById(movementId);
            List<ArtMovementBasicInfoRespDto> artMovementBasicInfoRespDtoList = new ArrayList<>();
            artMovementBasicInfoRespDtoList.add(ArtMovementBasicInfoRespDto.builder()
                    //流派id
                    .id(artMovement.getId())
                    //流派名称
                    .movementName(artMovement.getMovementName())
                    .build());

            //作品所属的艺术家基本信息（可能属于多个艺术家）
            Integer artistId = artWork.getArtistId();
            ArtArtist artArtist = artArtistMapper.getById(artistId);
            List<ArtArtistBasicInfoRespDto> artArtistBasicInfoRespDtoList = new ArrayList<>();
            artArtistBasicInfoRespDtoList.add(ArtArtistBasicInfoRespDto.builder()
                    //艺术家id
                    .id(artArtist.getId())
                    //艺术家名称
                    .artistName(artArtist.getArtistName())
                    .build());

            //作品所属的类别基本信息（可能属于多个类别）
            Integer categoryId = artWork.getCategoryId();
            ArtCategory artCategory = artCategoryMapper.getById(categoryId);
            List<ArtCategoryBasicInfoRespDto> artCategoryBasicInfoRespDtoList = new ArrayList<>();
            artCategoryBasicInfoRespDtoList.add(ArtCategoryBasicInfoRespDto.builder()
                    //类别id
                    .id(artCategory.getId())
                    //类别名称
                    .categoryName(artCategory.getCategoryName())
                    .build());

            //根据当前线程的用户id，判断用户是喜欢该作品
            Integer workId = artWork.getId();
            //默认用户不喜欢，如果数据库中有数据，则根据数据库的数据
            Boolean isLiked = false;
            ArtUserLikes artUserLikes = artUserLikesMapper.getByUserIdAndWorkId(userId, workId);
            if (artUserLikes != null && artUserLikes.getIsLiked() != null) {
                isLiked = artUserLikes.getIsLiked();
            }

            return ArtWorkInfoRespDto.builder()
                    //作品id
                    .id(artWork.getId())
                    //作品名称
                    .title(artWork.getTitle())
                    //作品描述
                    .description(artWork.getDescription())
                    //默认用户不喜欢，如果数据库中有数据，则根据数据库的数据
                    .isLiked(isLiked)
                    //作品的主图小图的URL
                    .primaryImageSmallUrl(artWork.getPrimaryImageSmallUrl())
                    //作品的主图大图的URL
                    .primaryImageUrl(artWork.getPrimaryImageUrl())
                    //作品所属的艺术家基本信息（可能属于多个艺术家）
                    .artArtistBasicInfoRespDtoList(artArtistBasicInfoRespDtoList)
                    //作品所属的流派基本信息（可能属于多个流派）
                    .artMovementBasicInfoRespDtoList(artMovementBasicInfoRespDtoList)
                    //作品所属的类别基本信息（可能属于多个类别）
                    .artCategoryBasicInfoRespDtoList(artCategoryBasicInfoRespDtoList)
                    //作品所属的话题基本信息（可能属于多个话题）
                    .artTopicBasicInfoRespDtoList(artTopicBasicInfoRespDtoList)
                    .build();*/
        }

    }

    /**
     * 缓存作品详细信息（除isLiked外，用户是否喜欢该艺术画）
     */
    @CacheWithLock(
            cacheName = "artworkInfoCache",
            key = "#artWork.id",   //从参数对象提取属性
            expireTime = CommonConsts.WORK_CACHE_EXPIRATION_TIME,
            cacheNull = true,
            enabled = true
    )
    @Override
    public ArtWorkInfoRespDto artworkInfoCache(ArtWork artWork){
        //作品所属的话题基本信息（可能属于多个话题）
        Integer topicId = artWork.getTopicId();
        ArtTopic artTopic = artTopicMapper.getById(topicId);
        List<ArtTopicBasicInfoRespDto> artTopicBasicInfoRespDtoList = new ArrayList<>();
        artTopicBasicInfoRespDtoList.add(ArtTopicBasicInfoRespDto.builder()
                //话题id
                .id(artTopic.getId())
                //话题名称
                .topicName(artTopic.getTopicName())
                .build());

        //作品所属的流派基本信息（可能属于多个流派）
        Integer movementId = artWork.getMovementId();
        ArtMovement artMovement = artMovementMapper.getById(movementId);
        List<ArtMovementBasicInfoRespDto> artMovementBasicInfoRespDtoList = new ArrayList<>();
        artMovementBasicInfoRespDtoList.add(ArtMovementBasicInfoRespDto.builder()
                //流派id
                .id(artMovement.getId())
                //流派名称
                .movementName(artMovement.getMovementName())
                .build());

        //作品所属的艺术家基本信息（可能属于多个艺术家）
        Integer artistId = artWork.getArtistId();
        ArtArtist artArtist = artArtistMapper.getById(artistId);
        List<ArtArtistBasicInfoRespDto> artArtistBasicInfoRespDtoList = new ArrayList<>();
        artArtistBasicInfoRespDtoList.add(ArtArtistBasicInfoRespDto.builder()
                //艺术家id
                .id(artArtist.getId())
                //艺术家名称
                .artistName(artArtist.getArtistName())
                .build());

        //作品所属的类别基本信息（可能属于多个类别）
        Integer categoryId = artWork.getCategoryId();
        ArtCategory artCategory = artCategoryMapper.getById(categoryId);
        List<ArtCategoryBasicInfoRespDto> artCategoryBasicInfoRespDtoList = new ArrayList<>();
        artCategoryBasicInfoRespDtoList.add(ArtCategoryBasicInfoRespDto.builder()
                //类别id
                .id(artCategory.getId())
                //类别名称
                .categoryName(artCategory.getCategoryName())
                .build());

        //根据当前线程的用户id，判断用户是喜欢该作品
        Integer workId = artWork.getId();
        //默认用户不喜欢，如果数据库中有数据，则根据数据库的数据
        /*Boolean isLiked = false;
        ArtUserLikes artUserLikes = artUserLikesMapper.getByUserIdAndWorkId(UserHolderUtility.getUserId(), workId);
        if (artUserLikes != null && artUserLikes.getIsLiked() != null) {
            isLiked = artUserLikes.getIsLiked();
        }*/

        return ArtWorkInfoRespDto.builder()
                //作品id
                .id(artWork.getId())
                //作品名称
                .title(artWork.getTitle())
                //作品描述
                .description(artWork.getDescription())
                //默认用户不喜欢，如果数据库中有数据，则根据数据库的数据
//                .isLiked(isLiked)
                //作品的主图小图的URL
                .primaryImageSmallUrl(artWork.getPrimaryImageSmallUrl())
                //作品的主图大图的URL
                .primaryImageUrl(artWork.getPrimaryImageUrl())
                //作品所属的艺术家基本信息（可能属于多个艺术家）
                .artArtistBasicInfoRespDtoList(artArtistBasicInfoRespDtoList)
                //作品所属的流派基本信息（可能属于多个流派）
                .artMovementBasicInfoRespDtoList(artMovementBasicInfoRespDtoList)
                //作品所属的类别基本信息（可能属于多个类别）
                .artCategoryBasicInfoRespDtoList(artCategoryBasicInfoRespDtoList)
                //作品所属的话题基本信息（可能属于多个话题）
                .artTopicBasicInfoRespDtoList(artTopicBasicInfoRespDtoList)
                .build();
    }


    /**
     * 根据艺术话题的ID或者作品类别的ID或者作品的创建者的ID或者作品所属的流派的ID 进行作品分页查找
     */
    @Override
    public RestResp<PageRespDto<ArtWorkBasicInfoRespDto>> listArtWorkByParamId(ArtWorkReqDto artWorkReqDto) {
        //构建分页对象
        Page<ArtWorkBasicInfoRespDto> page = new Page<>();
        //当前页数
        page.setCurrent(artWorkReqDto.getPageNum());
        //每页显示的条数
        page.setSize(artWorkReqDto.getPageSize());

        //进行分页查询
        List<ArtWork> artWorks = artWorkMapper.listArtWorkByParamId(page, artWorkReqDto);

        //返回的对象
        List<ArtWorkBasicInfoRespDto> ArtWorkBasicList = new ArrayList<>();
        for (ArtWork artWork : artWorks) {
            //转换为基础信息返回DTO并添加到返回列表中
//            ArtWorkBasicList.add(new ArtWorkBasicInfoRespDto(artWork.getId(), artWork.getTitle(), artWork.getPrimaryImageSmallUrl()));
            ArtWorkBasicList.add(
                    ArtWorkBasicInfoRespDto.builder()
                            //作品的唯一标识ID
                            .id(artWork.getId())
                            //作品的名称
                            .title(artWork.getTitle())
                            //作品 艺术家名字
                            .artistName(artArtistMapper.getById(artWork.getArtistId()).getArtistName())
                            //作品的主图小图的URL
                            .primaryImageSmallUrl(artWork.getPrimaryImageSmallUrl())
                            .build());
        }
        PageRespDto<ArtWorkBasicInfoRespDto> pageRespDto = new PageRespDto<>(page.getPages(), page.getSize(), page.getTotal(), ArtWorkBasicList);
        return RestResp.ok(pageRespDto);
    }

    /**
     * 用户推荐内容
     * 目前是 艺术作品中 点击量+分享量+下载量+喜欢量 前20个
     * 如果同一数量，则按艺术作品的id降序排列
     */
    @Override
    public RestResp<PageRespDto<ArtWorkBasicInfoRespDto>> userRecommend(PageReqDto pageReqDto) {
        //构建分页对象
        Page<ArtWorkBasicInfoRespDto> page = new Page<>(pageReqDto.getPageNum(), pageReqDto.getPageSize());
        List<Integer> artWorkIdList = artUserActionsMapper.getRecommendArtWorkId(page);
        List<ArtWorkBasicInfoRespDto> ArtWorkBasicList = new ArrayList<>();
        for (Integer artWorkId : artWorkIdList) {
            ArtWork artWork = artWorkMapper.getById(artWorkId);
            ArtWorkBasicList.add(
                    ArtWorkBasicInfoRespDto.builder()
                            //作品的唯一标识ID
                            .id(artWork.getId())
                            //作品的名称
                            .title(artWork.getTitle())
                            //作品 艺术家名字
                            .artistName(artArtistMapper.getById(artWork.getArtistId()).getArtistName())
                            //作品的主图小图的URL
                            .primaryImageSmallUrl(artWork.getPrimaryImageSmallUrl())
                            .build());
        }
        PageRespDto<ArtWorkBasicInfoRespDto> pageRespDto = new PageRespDto<>(page.getPages(), page.getSize(), page.getTotal(), ArtWorkBasicList);
        return RestResp.ok(pageRespDto);
    }


    /**
     * 查询所有的艺术作品信息，将其存入到ES中
     */
    @Override
    public List<ArtWorkEsRespDto> syncArtWorkToEs() {
        ArrayList<ArtWorkEsRespDto> artWorkEsRespDtos = new ArrayList<>();
        //查询所有的艺术作品信息
        List<ArtWork> artWorks = artWorkMapper.listAll();
        //根据查询的艺术作品ID查询该作品的统计信息（下载量、分享量、点击量、喜欢量）
        for (ArtWork artWork : artWorks) {
            ArtWorkEsRespDto artWorkEsRespDto = buildArtWorkEsRespDto(artWork);
            artWorkEsRespDtos.add(artWorkEsRespDto);
        }
        return artWorkEsRespDtos;
    }

    /**
     * 查询自上次同步以来新增或修改的艺术作品数据
     */
    @Override
    public List<ArtWorkEsRespDto> getModifiedArtWorks(LocalDateTime lastSyncTime) {
        ArrayList<ArtWorkEsRespDto> artWorkEsRespDtos = new ArrayList<>();
        //查询自上次同步以来新增或修改的艺术作品数据
        List<ArtWork> artWorks = artWorkMapper.selectModifiedArtWorks(lastSyncTime);
        //根据查询的艺术作品ID查询该作品的统计信息（下载量、分享量、点击量、喜欢量）
        for (ArtWork artWork : artWorks) {
            ArtWorkEsRespDto artWorkEsRespDto = buildArtWorkEsRespDto(artWork);
            artWorkEsRespDtos.add(artWorkEsRespDto);
        }
        return artWorkEsRespDtos;
    }

    /**
     * 根据艺术作品信息构建 ArtWorkEsRespDto 对象
     *
     * @param artWork 艺术作品信息
     * @return ArtWorkEsRespDto 对象
     */
    @Override
    public ArtWorkEsRespDto buildArtWorkEsRespDto(ArtWork artWork) {
        // 查询艺术家名字
        String artistName = artArtistMapper.getById(artWork.getArtistId()).getArtistName();
        // 查询话题名称
        String topicName = artTopicMapper.getById(artWork.getTopicId()).getTopicName();
        // 查询类别名称
        String categoryName = artCategoryMapper.getById(artWork.getCategoryId()).getCategoryName();
        // 查询流派名称
        String movementName = artMovementMapper.getById(artWork.getMovementId()).getMovementName();

        //先设置默认的统计信息全部为0
        ArtWorkEsRespDto artWorkEsRespDto = new ArtWorkEsRespDto(artWork.getId(), artWork.getTitle(), artistName, artWork.getPrimaryImageSmallUrl(), CommonConsts.STATISTICS_COUNT_INIT, CommonConsts.STATISTICS_COUNT_INIT, CommonConsts.STATISTICS_COUNT_INIT, CommonConsts.STATISTICS_COUNT_INIT, topicName, categoryName, movementName);

        // 查询统计信息
        ArtStatistics artStatistics = artStatisticsMapper.getByWorkId(artWork.getId());
        // 如果统计信息存在，更新 ArtWorkEsRespDto 的统计信息
        if (artStatistics != null) {
            //点击量
            artWorkEsRespDto.setClickCount(artStatistics.getViewCount());
            // 下载量
            artWorkEsRespDto.setDownloadCount(artStatistics.getDownloadCount());
            // 喜欢量
            artWorkEsRespDto.setLikeCount(artStatistics.getLikeCount());
            // 分享量
            artWorkEsRespDto.setShareCount(artStatistics.getShareCount());
        }

        return artWorkEsRespDto;
    }
}
